package com.sinodata.bsm.center.engine.notify.impl;

import java.io.IOException;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.jboss.remoting.samples.chat.exceptions.InitializeException;

import com.sino.uam.entity.UserInfo;
import com.sinodata.bsm.center.bean.EventPropHisBean;
import com.sinodata.bsm.center.cache.EventTypeCache;
import com.sinodata.bsm.center.cache.ResCache;
import com.sinodata.bsm.center.engine.notify.NotifyMode;
import com.sinodata.bsm.center.service.event.EventPropHisService;
import com.sinodata.bsm.center.service.event.EventService;
import com.sinodata.bsm.center.user.UserUtil;
import com.sinodata.bsm.center.util.spring.SpringContextHolder;
import com.sinodata.bsm.center.util.system.SystemContext;
import com.sinodata.bsm.common.constants.EventConstants;
import com.sinodata.bsm.common.exception.AppException;
import com.sinodata.bsm.common.vo.Event;
import com.sinodata.bsm.common.vo.EventCauses;
import com.sinodata.bsm.common.vo.EventRemark;
import com.sinodata.bsm.common.vo.EventType;
import com.sinodata.bsm.common.vo.Notify;
import com.sinodata.bsm.common.vo.Res;

/**
 * 
 * <p>
 * Description: 邮件通知实现类
 * </p>
 *
 * @author liulibo
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-8-9 PM 3:10:30      liulibo        1.0         To create
 * </p>
 *
 * @since 
 * @see
 */
public class MailNotifyModeImpl implements NotifyMode {

    private static final Logger logger = Logger.getLogger(MailNotifyModeImpl.class);

    private static EventService eventService = SpringContextHolder.getBean(EventService.class);

    private static EventPropHisService eventPropHisService = SpringContextHolder.getBean(EventPropHisService.class);

    private static EventTypeCache eventTypeCache = SpringContextHolder.getBean(EventTypeCache.class);

    private static ResCache resCache = SpringContextHolder.getBean(ResCache.class);

    private static String MAIL_TEMPLET = "WEB-INF/conf/";

    private Template template;

    private static final String NOTIFY_IMG = "notify_img";

    private static final String NOTIFY_TITLE = "notify_title";

    private static final String NOTIFY_MSG = "notify_msg";

    private static final String NOTIFY_RECEIVER = "notify_receiver";

    private static final String NOTIFY_TIME = "notify_time";

    private static final String NOTIFY_DATE = "notify_date";

    private static final String NOTIFY_EVENT_PROCESS = "notify_event_process";

    private static final String NOTIFY_EVENT_PROP = "notify_event_prop";

    private static final String NOTIFY_EVENT_REMARK = "notify_event_remark";

    private static final String EVENT_INFO = "event_info";

    private static final String EVENT_TYPE = "event_type";

    private static final String EVENT_STATUS = "event_status";

    private static final String EVENT_LEVEL = "event_level";

    private static final String EVENT_RES_NAME = "event_res_name";

    private static final String EVENT_OCCUR_TIME = "event_occur_time";

    private static final String EVENT_COUNT = "event_count";

    private static final String EVENT_LAST_OCCUR_TIME = "event_last_occur_time";

    private static final String EVENT_ACK_USER = "event_ack_user";

    private static final String EVENT_ACK_TIME = "event_ack_time";

    private static final String EVENT_CONFIRMER = "event_confirmer";

    private static final String EVENT_CONFIRM_TIME = "event_confirm_time";

    private static final String EVENT_CAUSES = "event_causes";

    private static final String EVENT_REMARK_TD_STYLE = "<td style='line-height:18px;height:26px;text-align:left;padding:3px;border-bottom:1px solid #e1eafb;border-right:1px solid #e1eafb; font-size:12px;'>";

    private static final String EVENT_PROP_LI_STYLE = "<li style=' line-height:22px;float:left;text-align:left;width:100%; list-style:none;'> ";

    private static final String EVENT_PROP_TITILE_SPAN_STYLE = "<span  style='display:block; color:#000; height:22px; width:100px; float:left; background:#fff; text-align:right; padding-right:2px;'>";

    private static final String EVENT_PROP_SPAN_STYLE = "<span style='width:600px;display:block;float:left;text-align:left;'>";

    /**
     * 构造方法
     */
    public MailNotifyModeImpl() {
        try {
            if (template == null) {
                initTemplet(MAIL_TEMPLET);
            }
        } catch (AppException e) {
            logger.error("init templet error", e);
        }
    }

    /*
     * (non-Javadoc)
     * @see com.sinodata.bsm.center.engine.notify.NotifyMode#createAlarmMessage(com.sinodata.bsm.common.vo.Event)
     */
    @Override
    public String createNotifyMessage(Event event) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String date = formatter.format(event.getOccurTime());
        StringBuilder strBuilder = new StringBuilder();
        strBuilder.append("【" + EventConstants.getLevelDesc(event.getLevel()) + "】");
        String notifyMessage = event.getMsg();
        //生成消息,按事件表达式重新生成, // 去掉实时生成
        //        if (event.getMsgExpr() != null && !event.getMsgExpr().equals("") && event.getCatalog() != EventConstants.CATALOG_USABLEEVENT) {
        //            try {
        //                Object msg = Expressions.eval(event.getMsgExpr());
        //                if (msg != null && msg instanceof String) {
        //                    notifyMessage = (String) msg;
        //                }
        //            } catch (Exception e) {
        //                logger.error("failed to calc real-time notify message,used original notify message", e);
        //            }
        //        }
        strBuilder.append(notifyMessage);
        strBuilder.append(" ");
        strBuilder.append(date);
        return strBuilder.toString();
    }

    /*
     * (non-Javadoc)
     * @see com.sinodata.bsm.center.engine.notify.NotifyMode#createResumeMessage(com.sinodata.bsm.common.vo.Event)
     */
    @Override
    public String createResumeMessage(Event eventValue) {
        StringBuilder sb = new StringBuilder();
        sb.append("【故障已恢复】【系统自动清除事件】");
        sb.append(eventValue.getMsg());
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String date = formatter.format(eventValue.getOccurTime());
        sb.append(" ");
        sb.append(date);
        return sb.toString();
    }

    /*
     * (non-Javadoc)
     * @see com.sinodata.bsm.center.engine.notify.NotifyMode#getNotifyDestination(com.sino.uam.entity.UserInfo)
     */
    @Override
    public String getNotifyDestination(UserInfo userInfo) {
        return userInfo.getEmail();
    }

    /* 
     * (non-Javadoc)
     * @see com.sinodata.bsm.center.engine.notify.NotifyMode#createMsg()
     */
    @Override
    public String createMsg(Notify notify) {
        try {
            return buildHtmlNotifyMessage(notify);
        } catch (AppException e) {
            logger.error("build html notify message error", e);
        }
        return null;
    }

    /**
     * 构建网页通知消息
     * 
     * @param notify
     * @return
     * @throws AppException 
     */
    private String buildHtmlNotifyMessage(Notify notify) throws AppException {
        Map<String, String> parameterMap = new HashMap<String, String>();
        Long eventId = notify.getEventId();
        Event event = eventService.getEventById(eventId);
        if (event == null || (event.getCatalog() != EventConstants.CATALOG_FAULTEVENT && event.getCatalog() != EventConstants.CATALOG_REFAULTEVENT)) {
            return notify.getMsg();
        }
        String notifyImg = "images/titleBg.png";
        String notifyTitle = "";
        if (event.getCatalog() == EventConstants.CATALOG_FAULTEVENT) {
            notifyImg = "images/titleBg1.png";
            notifyTitle = "故障通知详细信息";
        } else {
            //恢复事件
            notifyImg = "images/titleBg.png";
            notifyTitle = "故障恢复通知信息";
            //被清除的事件
            Event confirmEvent = eventService.findEventByConfirmEventId(eventId);
            if (confirmEvent != null) {
                event = confirmEvent;
            }
        }
        String format = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat simple = new SimpleDateFormat(format);
        parameterMap.put(NOTIFY_IMG, notifyImg);
        parameterMap.put(NOTIFY_TITLE, notifyTitle);
        //为什么要截取？ 去掉截取
        String notifyMsg = notify.getMsg();//.substring(0, notify.getMsg().length() - 16);
        parameterMap.put(NOTIFY_MSG, notifyMsg);
        UserInfo user = UserUtil.getInstance().getUserById(notify.getUser());
        parameterMap.put(NOTIFY_RECEIVER, user.getEmail());
        parameterMap.put(NOTIFY_TIME, simple.format(notify.getTime()));
        parameterMap.put(NOTIFY_EVENT_PROCESS, buildProcess(event));
        buildEventInfo(event, parameterMap, simple);
        List<EventPropHisBean> eventPropHisBeans = eventPropHisService.getEventPropHisByEventId(event.getId());
        String notifyEventProp = "";
        if (eventPropHisBeans != null && eventPropHisBeans.size() > 0) {
            notifyEventProp = buildPropInfo(eventPropHisBeans);
        }
        parameterMap.put(NOTIFY_EVENT_PROP, notifyEventProp);
        List<EventRemark> eventRemarks = eventService.findEventRemarkByEventId(event.getId());
        String notifyEventRemark = "";
        if (eventRemarks != null && eventRemarks.size() > 0) {
            notifyEventRemark = buildEventRemark(eventRemarks, simple);
        }
        parameterMap.put(NOTIFY_EVENT_REMARK, notifyEventRemark);
        String dateFormat = "yyyy年MM月dd日";
        SimpleDateFormat dateSimple = new SimpleDateFormat(dateFormat);
        String notifyDate = dateSimple.format(System.currentTimeMillis());
        parameterMap.put(NOTIFY_DATE, notifyDate);
        return formatHtmlMail(parameterMap);
    }

    /**
     * 格式化邮件
     * 
     * @param notifyImg
     * @param notifyTitle
     * @param notifyReceiver
     * @param notifyTime
     * @param notifyEventProcess
     * @param notifyEventInfo
     * @param notifyEventProp
     * @param notifyEventRemark
     * @param notifyDate
     * @return
     * @throws AppException
     */
    private String formatHtmlMail(Map<String, String> parameterMap) throws AppException {
        VelocityContext context = new VelocityContext();
        //循环
        Iterator<String> it = parameterMap.keySet().iterator();
        while (it.hasNext()) {
            String key = it.next();
            context.put(key, parameterMap.get(key));
        }
        //end
        StringWriter writer = new StringWriter();
        try {
            template.merge(context, writer);
        } catch (IOException e) {
            throw new AppException("模板匹配时出错");
        }
        return writer.toString();
    }

    /**
     * 构建事件状态流程图HTML
     * 
     * @param event
     * @return
     */
    private String buildProcess(Event event) {
        String processStatus = "images/t0.jpg";
        if (EventConstants.STATUS_NEW == event.getStatus()) {
            processStatus = "images/t1.jpg";
        } else if (EventConstants.STATUS_ACKNOWLEDGED == event.getStatus()) {
            processStatus = "images/t2.jpg";
        } else if (EventConstants.STATUS_CONFIRMED == event.getStatus()) {
            processStatus = "images/t3.jpg";
        }
        return processStatus;
    }

    /**
     * 构建事件基本信息
     * 
     * @param event
     * @return
     */
    private void buildEventInfo(Event event, Map<String, String> parameterMap, SimpleDateFormat simple) {
        parameterMap.put(EVENT_INFO, event.getMsg());
        EventType eventType = eventTypeCache.get(event.getEventTypeId());
        if (eventType != null) {
            parameterMap.put(EVENT_TYPE, eventType.getName());
        } else {
            parameterMap.put(EVENT_TYPE, event.getEventTypeId() + "(已删除)");
        }
        parameterMap.put(EVENT_STATUS, EventConstants.getStatusDesc(event.getStatus()));
        parameterMap.put(EVENT_LEVEL, EventConstants.getLevelDesc(event.getLevel()));
        Res res = resCache.get(event.getResId());
        if (res != null) {
            parameterMap.put(EVENT_RES_NAME, res.getName());
        } else {
            parameterMap.put(EVENT_RES_NAME, event.getResId() + "(已删除)");
        }
        parameterMap.put(EVENT_OCCUR_TIME, simple.format(event.getOccurTime()));
        parameterMap.put(EVENT_COUNT, event.getCount() + "");
        parameterMap.put(EVENT_LAST_OCCUR_TIME, event.getLastOccurTime() == null ? " " : simple.format(event.getLastOccurTime()));
        if (event.getAckUser() != null) {
            UserInfo user = UserUtil.getInstance().getUserById(event.getAckUser());
            if (user != null) {
                parameterMap.put(EVENT_ACK_USER, user.getFullName() == null ? " " : user.getFullName());
            } else {
                parameterMap.put(EVENT_ACK_USER, event.getAckUser() + "(已删除)");
            }
        } else {
            parameterMap.put(EVENT_ACK_USER, " ");
        }
        parameterMap.put(EVENT_ACK_TIME, event.getAckTime() == null ? " " : simple.format(event.getAckTime()));
        if (event.getConfirmType() != null && event.getConfirmType() == EventConstants.CONFIRM_TYPE_USER && event.getConfirmer() != null) {
            UserInfo user = UserUtil.getInstance().getUserById(event.getConfirmer());
            if (user != null) {
                parameterMap.put(EVENT_CONFIRMER, user.getFullName() == null ? " " : user.getFullName());
            } else {
                parameterMap.put(EVENT_CONFIRMER, event.getConfirmer() + "(已删除)");
            }
        } else {
            if (event.getConfirmType() != null && event.getConfirmType() == EventConstants.CONFIRM_TYPE_EVENT) {
                parameterMap.put(EVENT_CONFIRMER, "系统");
            } else {
                parameterMap.put(EVENT_CONFIRMER, " ");
            }
        }
        parameterMap.put(EVENT_CONFIRM_TIME, event.getConfirmTime() == null ? " " : simple.format(event.getConfirmTime()));
        EventCauses eventCauses = eventService.getEventCausesByEventId(event.getId());
        if (eventCauses != null) {
            parameterMap.put(EVENT_CAUSES, eventCauses.getTitle() == null ? " " : eventCauses.getTitle());
        } else {
            parameterMap.put(EVENT_CAUSES, " ");
        }
    }

    /**
     * 构建指标信息HTML
     * 
     * @param eventPropHisBeans
     * @return
     */
    private String buildPropInfo(List<EventPropHisBean> eventPropHisBeans) {
        StringBuilder sb = new StringBuilder("");
        for (EventPropHisBean eventPropHisBean : eventPropHisBeans) {
            sb.append(EVENT_PROP_LI_STYLE);
            sb.append(EVENT_PROP_TITILE_SPAN_STYLE);
            sb.append(eventPropHisBean.getPropName());
            sb.append("：</span>");
            sb.append(EVENT_PROP_SPAN_STYLE);
            sb.append(eventPropHisBean.getEventPropHis().getPropValue());
            String dataUnit = eventPropHisBean.getDataUnit();
            if (dataUnit != null) {
                sb.append(dataUnit);
            }
            sb.append("</span></li>");
        }
        return sb.toString();
    }

    /**
     * 构建事件备注信息HTML
     * 
     * @param eventRemarks
     * @return
     */
    private String buildEventRemark(List<EventRemark> eventRemarks, SimpleDateFormat simple) {
        StringBuilder sb = new StringBuilder("");
        for (EventRemark eventRemark : eventRemarks) {
            sb.append("<tr>");
            sb.append(EVENT_REMARK_TD_STYLE);
            sb.append(simple.format(eventRemark.getTime()));
            sb.append("</td>");
            sb.append(EVENT_REMARK_TD_STYLE);
            sb.append(UserUtil.getInstance().getUserById(eventRemark.getUser()).getFullName());
            sb.append("</td>");
            sb.append(EVENT_REMARK_TD_STYLE);
            sb.append(eventRemark.getRemarks() == null ? " " : eventRemark.getRemarks());
            sb.append("</td></tr>");
        }
        return sb.toString();
    }

    /**
     * 初始化邮件模板信息
     * 
     * @param templet
     * @throws InitializeException
     * @throws AppException 
     */
    private void initTemplet(String templetPath) throws AppException {
        Properties p = new Properties();
        p.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, SystemContext.getProperty("AppContextPath") + MAIL_TEMPLET);//这是模板所在路径 
        VelocityEngine velocityEngine = new VelocityEngine();
        try {
            velocityEngine.init(p);
        } catch (Exception e) {
            logger.warn("velocityEngine初始化失败!", e);
        }
        try {
            template = velocityEngine.getTemplate("htmlmail.vm", "utf-8");
        } catch (ResourceNotFoundException e) {
            throw new AppException("mail模板文件未发现");
        } catch (ParseErrorException e) {
            throw new AppException("mail模板解析错误!");
        } catch (Exception e) {
            throw new AppException("模板初始化时失败!");
        }
    }

}